// Scripted by Xinef

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "Spell.h"
#include "SpellScript.h"
#include "GameEventMgr.h"
#include "Player.h"


///////////////////////////////
// SPELLS
///////////////////////////////

enum Mistletoe
{
    SPELL_CREATE_MISTLETOE          = 26206,
    SPELL_CREATE_HOLLY              = 26207,
    SPELL_CREATE_SNOWFLAKES         = 45036
};

class spell_winter_veil_mistletoe : public SpellScriptLoader
{
    public:
        spell_winter_veil_mistletoe() : SpellScriptLoader("spell_winter_veil_mistletoe") { }

        class spell_winter_veil_mistletoe_SpellScript : public SpellScript
        {
            PrepareSpellScript(spell_winter_veil_mistletoe_SpellScript);

            bool Validate(SpellInfo const* /*spell*/)
            {
                if (!sSpellMgr->GetSpellInfo(SPELL_CREATE_MISTLETOE) ||
                    !sSpellMgr->GetSpellInfo(SPELL_CREATE_HOLLY) ||
                    !sSpellMgr->GetSpellInfo(SPELL_CREATE_SNOWFLAKES))
                    return false;
                return true;
            }

            void HandleScript(SpellEffIndex /*effIndex*/)
            {
                if (Player* target = GetHitPlayer())
                {
                    uint32 spellId = RAND(SPELL_CREATE_HOLLY, SPELL_CREATE_MISTLETOE, SPELL_CREATE_SNOWFLAKES);
                    GetCaster()->CastSpell(target, spellId, true);
                }
            }

            void Register()
            {
                OnEffectHitTarget += SpellEffectFn(spell_winter_veil_mistletoe_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
            }
        };

        SpellScript* GetSpellScript() const
        {
            return new spell_winter_veil_mistletoe_SpellScript();
        }
};

enum winterWondervoltTrap
{
	SPELL_WINTER_WONDERVOLT_GREEN_WOMEN		= 26272,
	SPELL_WINTER_WONDERVOLT_GREEN_MAN		= 26157,
	SPELL_WINTER_WONDERVOLT_RED_WOMEN		= 26274,
	SPELL_WINTER_WONDERVOLT_RED_MAN			= 26273,
};

class spell_winter_wondervolt_trap : public SpellScriptLoader
{
    public:
    spell_winter_wondervolt_trap() : SpellScriptLoader("spell_winter_wondervolt_trap") {}

    class spell_winter_wondervolt_trap_SpellScript : public SpellScript
    {
        PrepareSpellScript(spell_winter_wondervolt_trap_SpellScript);

        void HandleScriptEffect(SpellEffIndex /*effIndex*/)
        {
            if (Player* target = GetHitPlayer())
            {
                // check presence
                if (target->HasAuraType(SPELL_AURA_TRANSFORM))
                    return;

				uint32 spellId = 0;
				if (target->getGender() == GENDER_MALE)
					spellId = RAND<uint32>(SPELL_WINTER_WONDERVOLT_RED_MAN, SPELL_WINTER_WONDERVOLT_GREEN_MAN);
				else
					spellId = RAND<uint32>(SPELL_WINTER_WONDERVOLT_RED_WOMEN, SPELL_WINTER_WONDERVOLT_GREEN_WOMEN);

                // cast
                target->CastSpell(target, spellId, true);
                return;
            }
        }

        void Register()
        {
            OnEffectHitTarget += SpellEffectFn(spell_winter_wondervolt_trap_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
        }
    };

    SpellScript* GetSpellScript() const
    {
        return new spell_winter_wondervolt_trap_SpellScript();
    }
};

enum crashinTrashin
{
	SPELL_BLUE_CAR_VISUAL				= 75110,
	SPELL_RED_CAR_VISUAL				= 49384,
	NPC_RED_RACER						= 27664,
	NPC_BLUE_RACER						= 40281,

	SPELL_RACER_DEATH_VISUAL			= 49337,
	SPELL_RACER_CHARGE_TO_OBJECT		= 49302,
	SPELL_RACER_KILL_COUNTER			= 49444,
	SPELL_RACER_SLAM_HIT				= 49324,
	SPELL_RACER_FLAMES					= 49328,

	RACER_ACHI_CRITERIA					= 4090,
};

class spell_winter_veil_racer_rocket_slam : public SpellScriptLoader
{
    public:
    spell_winter_veil_racer_rocket_slam() : SpellScriptLoader("spell_winter_veil_racer_rocket_slam") {}

    class spell_winter_veil_racer_rocket_slam_SpellScript : public SpellScript
    {
        PrepareSpellScript(spell_winter_veil_racer_rocket_slam_SpellScript);

        void HandleTriggerSpell(SpellEffIndex /*effIndex*/)
        {
            Unit* caster = GetCaster();
			PreventHitEffect(EFFECT_0);
			PreventHitEffect(EFFECT_1);

			std::list<Creature*> unitList;
			Unit* target = NULL;
			caster->GetCreaturesWithEntryInRange(unitList, 30.0f, NPC_BLUE_RACER);
			if (!unitList.empty())
				for (std::list<Creature*>::const_iterator itr = unitList.begin(); itr != unitList.end(); ++itr)
					if (caster->HasInLine((*itr), 1.0f) && (*itr)->GetGUID() != caster->GetGUID())
					{
						target = (*itr);
						break;
					}
			if (!target)
			{
				unitList.clear();
				caster->GetCreaturesWithEntryInRange(unitList, 30.0f, NPC_RED_RACER);
				if (!unitList.empty())
					for (std::list<Creature*>::const_iterator itr = unitList.begin(); itr != unitList.end(); ++itr)
						if (caster->HasInLine((*itr), 1.0f) && (*itr)->GetGUID() != caster->GetGUID())
						{
							target = (*itr);
							break;
						}
			}

			if (target)
			{
				caster->CastSpell(target, SPELL_RACER_CHARGE_TO_OBJECT, true);
				caster->CastSpell(target, SPELL_RACER_SLAM_HIT, true);
			}
			else
			{
				Position pos;
				float x = caster->GetPositionX()+30*cos(caster->GetOrientation());
				float y = caster->GetPositionY()+30*sin(caster->GetOrientation());
				pos.Relocate(x, y, caster->GetMap()->GetHeight(x, y, MAX_HEIGHT)+0.5f);
				//caster->GetFirstCollisionPosition(pos, 30.0f, caster->GetOrientation());
				caster->CastSpell(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), SPELL_RACER_CHARGE_TO_OBJECT, true);
			}
        }

        void Register()
        {
            OnEffectLaunch += SpellEffectFn(spell_winter_veil_racer_rocket_slam_SpellScript::HandleTriggerSpell, EFFECT_1, SPELL_EFFECT_TRIGGER_SPELL);
        }
    };

    SpellScript* GetSpellScript() const
    {
        return new spell_winter_veil_racer_rocket_slam_SpellScript();
    }
};

class spell_winter_veil_racer_slam_hit : public SpellScriptLoader
{
    public:
    spell_winter_veil_racer_slam_hit() : SpellScriptLoader("spell_winter_veil_racer_slam_hit") {}

    class spell_winter_veil_racer_slam_hit_SpellScript : public SpellScript
    {
        PrepareSpellScript(spell_winter_veil_racer_slam_hit_SpellScript);

        void HandleScriptEffect(SpellEffIndex /*effIndex*/)
        {
            Unit* caster = GetCaster();
			Creature* target = GetHitCreature();
			if (!target || caster == target)
				return;

			target->CastSpell(target->GetPositionX()+irand(-10, 10), target->GetPositionY()+irand(-10, 10), target->GetPositionZ() , SPELL_RACER_DEATH_VISUAL, true);
			target->DespawnOrUnsummon(3000);
			target->CastSpell(target, SPELL_RACER_FLAMES, true);
			caster->CastSpell(caster, SPELL_RACER_KILL_COUNTER, true);

			if (Player* targetSummoner = target->GetCharmerOrOwnerPlayerOrPlayerItself())
			{
				//targetSummoner->RemoveCriteriaProgress(sAchievementCriteriaStore.LookupEntry(RACER_ACHI_CRITERIA)); !ZOMG, ADD ACCESSOR
				targetSummoner->RemoveAurasDueToSpell(SPELL_RACER_KILL_COUNTER);
			}
        }

        void Register()
        {
            OnEffectHitTarget += SpellEffectFn(spell_winter_veil_racer_slam_hit_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
        }
    };

    SpellScript* GetSpellScript() const
    {
        return new spell_winter_veil_racer_slam_hit_SpellScript();
    }
};

enum airRifle
{
	SPELL_AIR_RIFLE_RIGHT_IN_THE_EYE		= 65577,
	SPELL_AIR_RIFLE_STARLED					= 61862,
	SPELL_AIR_RIFLE_HIT						= 61866,
	SPELL_AIR_RIFLE_HIT_TRIGGER				= 65576,
	SPELL_AIR_RIFLE_PELTED_DAMAGE			= 67531,
};

class spell_winter_veil_shoot_air_rifle : public SpellScriptLoader
{
    public:
    spell_winter_veil_shoot_air_rifle() : SpellScriptLoader("spell_winter_veil_shoot_air_rifle") {}

    class spell_winter_veil_shoot_air_rifle_SpellScript : public SpellScript
    {
        PrepareSpellScript(spell_winter_veil_shoot_air_rifle_SpellScript);

        void HandleScriptEffect(SpellEffIndex /*effIndex*/)
        {
			Unit* caster = GetOriginalCaster();
			Unit* target = GetHitUnit();
			if (!target)
				return;

			if (GetSpellInfo()->Id == SPELL_AIR_RIFLE_HIT_TRIGGER)
			{
				if (!caster->IsFriendlyTo(target))
					caster->CastSpell(target, SPELL_AIR_RIFLE_PELTED_DAMAGE, true, NULL, NULL, caster->GetGUID());
			}
			else
			{
				uint8 rand = urand(0, 99);
				if (rand < 15)
					caster->CastSpell(caster, SPELL_AIR_RIFLE_RIGHT_IN_THE_EYE, true, NULL, NULL, caster->GetGUID());
				else if (rand < 35)
					caster->CastSpell(target, SPELL_AIR_RIFLE_STARLED, true, NULL, NULL, caster->GetGUID());
				else
					caster->CastSpell(target, SPELL_AIR_RIFLE_HIT, true, NULL, NULL, caster->GetGUID());
			}
        }

        void Register()
        {
			if (m_scriptSpellId == SPELL_AIR_RIFLE_HIT_TRIGGER)
				OnEffectHitTarget += SpellEffectFn(spell_winter_veil_shoot_air_rifle_SpellScript::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
			else
				OnEffectHitTarget += SpellEffectFn(spell_winter_veil_shoot_air_rifle_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
        }
    };

    SpellScript* GetSpellScript() const
    {
        return new spell_winter_veil_shoot_air_rifle_SpellScript();
    }
};

void AddSC_event_winter_veil_scripts()
{
	// Spells
	new spell_winter_veil_mistletoe();
	new spell_winter_wondervolt_trap();
	new spell_winter_veil_racer_rocket_slam();
	new spell_winter_veil_racer_slam_hit();
	new spell_winter_veil_shoot_air_rifle();
}